from starlette.endpoints import HTTPEndpoint
from starlette.responses import PlainTextResponse
import logging
import config
import xml.etree.ElementTree as ET
import wx_msg_process
import core.public_authorize as pub_authorize


class PublicCoreRoute(HTTPEndpoint):

    def __init__(self, scope):
        super().__init__(scope)
        self._logger = logging.getLogger(type(self).__name__)

    async def get(self, request):
        signature = request.query_params["signature"]
        echo_str = request.query_params["echostr"]
        timestamp = request.query_params["timestamp"]
        nonce_str = request.query_params["nonce"]
        if wx_msg_process.verify_signature_public(signature, timestamp, nonce_str, config.PUB_APP_TOKEN):
            self._logger.info("微信回调验证成功。")
            decrypt_echo_str = echo_str
            self._logger.debug(decrypt_echo_str)
            return PlainTextResponse(decrypt_echo_str)
        else:
            self._logger.warning("微信回调验证失败，签名不符。")
            return PlainTextResponse("Invalid Request")

    async def post(self, request):
        xml_body = await request.body()
        parsed_request = ET.fromstring(xml_body)
        signature = request.query_params["signature"]
        timestamp = request.query_params["timestamp"]
        nonce_str = request.query_params["nonce"]

        # self._logger.debug(f"消息签名是{signature}")
        # self._logger.debug(f"已加密消息是{encrypted_message}")

        if wx_msg_process.verify_signature_public(signature, timestamp, nonce_str, config.PUB_APP_TOKEN):
            self._logger.debug("[MESSAGE_CENTER] 接收到的消息验证成功。")
            if parsed_request.find("Encrypt") is not None:
                encrypted_message = parsed_request.findtext("Encrypt")
                decrypted_message = wx_msg_process.decrypt_message(encrypted_message,
                                                                   config.PUB_APP_ENCRYPT_KEY).decode("utf-8")
                # self._logger.debug(f"[DECRYPT_MESSAGE] {decrypted_message}")
                decoded_message = ET.fromstring(decrypted_message)
                event = decoded_message.findtext("Event").lower()
                msg_type = decoded_message.findtext("MsgType").lower()
                message = decoded_message
            else:
                event = parsed_request.findtext("Event").lower()
                msg_type = parsed_request.findtext("MsgType").lower()
                message = parsed_request

            if event == "subscribe":
                user_info = pub_authorize.fetch_user_info(message.findtext("FromUserName"))
                pub_authorize.save_or_update_user(user_info["openid"], user_info["nickname"])
                pub_authorize.send_welcome_wagon(user_info["openid"])
                self._logger.info(f"[SUBSCRIBE] 用户 {user_info['nickname']} 已经完成了关注，并发送了欢迎词。")
            if event == "templatesendjobfinish":
                from model.ModPowerSupplyBureauOperator import PowerSupplyBureauOperator
                from sqlalchemy.exc import SQLAlchemyError
                from database import Session
                session = Session()
                try:
                    user_openid = message.findtext("FromUserName")
                    bureau_user = session.query(PowerSupplyBureauOperator)\
                        .filter(PowerSupplyBureauOperator.openid == user_openid)\
                        .first()
                    status = message.findtext("Status").lower()
                    if status.startswith("success"):
                        self._logger.info(f"[TEMPLATE_SEND] 向用户 {bureau_user.remark}（{user_openid}） "
                                          f"发送模板消息成功。")
                    else:
                        self._logger.info(f"[TEMPLATE_SEND] 向用户 {bureau_user.remark}（{user_openid}） "
                                          f"发送模板消息失败，错误信息：{status}")
                except SQLAlchemyError:
                    self._logger.error(f"[TEMPLATE_SEND] 获取用户 {user_openid} 信息出现错误。")
                finally:
                    session.rollback()
                    session.close()
            if event is None:
                if msg_type == "text":
                    pass

        return PlainTextResponse("success")
